package com.scarecrow.compack.component.movement {
	import com.scarecrow.olga.game.component.UpdateableComponent;
	import com.scarecrow.olga.util.logging.Profiler;
	import com.scarecrow.olga.util.math.TrigUtil;
	import flash.geom.Point;
	
	/**
	 * ...
	 * @author Santiago.J.Elizalde
	 */
	public class PhysicsMover extends UpdateableComponent {
		
		public static const GRAVITY:Number = 0.45;
		public static const FRICTION:Number = 0.005;
		public static const ELASTICITY:Number = 0.75;
		public static const STOP_THRESHOLD:Number = 0.10;
		
		private var maxVel:Number;
		private var xVel:Number;
		private var yVel:Number;
		private var _angle:Number;
		
		private var idleCount:int;
		
		public function PhysicsMover(maxVelocity:Number) {
			maxVel = maxVelocity;
		}
		
		public function applyForce(strength:Number, angle:Number):void {
			angle = TrigUtil.radFromDeg(angle);
			xVel += strength * Math.cos(angle);
			yVel += strength * Math.sin(angle);
			_angle = Math.atan2(xVel, yVel);
			update();
		}
		public function setForce(strength:Number, angle:Number):void {
			angle = TrigUtil.radFromDeg(angle);
			xVel = strength * Math.cos(angle);
			yVel = strength * Math.sin(angle);
			_angle = angle
			update();
		}
		public function cancelForce():void {
			yVel = xVel = _angle = 0;
		}
		public function get xVelocity():Number {
			return xVel;
		}
		public function get yVelocity():Number {			
			return yVel;
		}
		public function get angle():Number {
			return TrigUtil.degFromRad(_angle);
		}
		override protected function initialize():void {
			cancelForce();
		}
		override public function update(ms:uint = 0):void {
			Profiler.start("physicsMover");
			var pos:Point = owner.getProp("pos");
			if (pos) {
				calculateVelocity();
				if (((pos.x + xVel) < 800 || xVel < 0) && ((pos.x + xVel) > 0 || xVel > 0)) {
					pos.x += xVel;
				} else {
					xVel *= (-1*ELASTICITY)*(1-FRICTION);
				}
				if (((pos.y + yVel) < 600 || yVel < 0) && ((pos.y + yVel) > 0 || yVel > 0)) {
					pos.y += yVel;
				} else {
					if (yVel > GRAVITY * (1 - FRICTION)) {
						yVel *= (-1*ELASTICITY)*(1-FRICTION);
					} else {
						yVel = 0;
					}
				}
			}
			if (Math.abs(xVel) < STOP_THRESHOLD && Math.abs(yVel) < STOP_THRESHOLD) {
				idleCount++;
			} else {
				idleCount = 0;
			}
			enabled = idleCount < 5;
			Profiler.end("physicsMover");
		}
		
		private function calculateVelocity():void {
			xVel = Math.abs(xVel) >= STOP_THRESHOLD ? xVel * (1-FRICTION) : 0;
			if (Math.abs(xVel) > maxVel) {
				xVel = xVel > 0 ? maxVel : maxVel*-1;
			}
			yVel = (yVel + GRAVITY) * (1 - FRICTION);
			yVel = Math.abs(yVel) >= STOP_THRESHOLD ? yVel : 0;
			if (Math.abs(yVel) > maxVel) {
				yVel = yVel > 0 ? maxVel : maxVel*-1;
			}
		}
		
		override protected function releaseGameObject():void {
			
		}
	}
}